#include "processinfo.h"

#ifdef __linux__
#include <time.h>
unsigned long GetTickCount()
{
    struct timespec ts;

    clock_gettime(CLOCK_MONOTONIC, &ts);

    return (ts.tv_sec * 1000 + ts.tv_nsec / 1000000);

}
#endif
ProcessInfo::ProcessInfo()
{
#ifdef _WIN32
	SYSTEM_INFO SystemInfo;
    GetSystemInfo(&SystemInfo);
	cpuNum=SystemInfo.dwNumberOfProcessors;

	percent = 0; 

	DWORD pid = GetCurrentProcessId();   
	hd  = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid); 
	if( hd==NULL ){
		return;
	}
#else
	cpuNum = sysconf(_SC_NPROCESSORS_ONLN);
	pid=getpid();
	maxMem=0;
#endif
	GetTime(oldp);
	t1 = GetTickCount();
}

ProcessInfo::~ProcessInfo()
{
#ifdef _WIN32
	if( hd!=NULL ){
		CloseHandle(hd);
	}
#else
#endif
}
#ifdef _WIN32
__int64 ProcessInfo::FileTimeToInt64(const FILETIME& time)
{
	ULARGE_INTEGER tt;
	tt.LowPart = time.dwLowDateTime;
	tt.HighPart = time.dwHighDateTime;
	return(tt.QuadPart);
}

 
int ProcessInfo::GetTime(int64_t& proc)
{
	if( hd==NULL )
	       return(-1);
	FILETIME create;
	FILETIME exit;
	FILETIME ker; 
	FILETIME user; 

    if( !GetProcessTimes(hd, &create, &exit, &ker, &user) ){
       return(-1);
    }

    proc = (FileTimeToInt64(ker) + FileTimeToInt64(user))/10000;
    return(0);
}

void ProcessInfo::GetMemoryInfo(unsigned int& topmem,unsigned int& mem)  
{  
    HANDLE handle=GetCurrentProcess();  
    PROCESS_MEMORY_COUNTERS pmc;  
    GetProcessMemoryInfo(handle,&pmc,sizeof(pmc));  
	topmem=pmc.PeakWorkingSetSize/1024;
	mem=pmc.WorkingSetSize/1024; 
}
#else
int ProcessInfo::GetProcCpuInfo(pid_t pid, procinfo * pinfo)
{
  char szFileName [256],
    szStatStr [2048],
    *s, *t;
  FILE *fp;
  struct stat st;

  if (NULL == pinfo) {
    errno = EINVAL;
    return -1;
  }

  sprintf (szFileName, "/proc/%u/stat", (unsigned) pid);

  if (-1 == access (szFileName, R_OK)) {
    return (pinfo->pid = -1);
  } /** if **/

  if (-1 != stat (szFileName, &st)) {
  pinfo->euid = st.st_uid;
  pinfo->egid = st.st_gid;
  } else {
  pinfo->euid = pinfo->egid = -1;
  }


  if ((fp = fopen (szFileName, "r")) == NULL) {
    return (pinfo->pid = -1);
  } /** IF_NULL **/

  if ((s = fgets (szStatStr, 2048, fp)) == NULL) {
    fclose (fp);
    return (pinfo->pid = -1);
  }

  /** pid **/
  sscanf (szStatStr, "%u", &(pinfo->pid));
  s = strchr (szStatStr, '(') + 1;
  t = strchr (szStatStr, ')');
  strncpy (pinfo->exName, s, t - s);
  pinfo->exName [t - s] = 0;

  sscanf (t + 2, "%c %d %d %d %d %d %u %u %u %u %u %d %d %d %d %d %d %u %u %d %u %u %u %u %u %u %u %u %d %d %d %d %u",
  /*       1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33*/
  &(pinfo->state),
  &(pinfo->ppid),
  &(pinfo->pgrp),
  &(pinfo->session),
  &(pinfo->tty),
  &(pinfo->tpgid),
  &(pinfo->flags),
  &(pinfo->minflt),
  &(pinfo->cminflt),
  &(pinfo->majflt),
  &(pinfo->cmajflt),
  &(pinfo->utime),
  &(pinfo->stime),
  &(pinfo->cutime),
  &(pinfo->cstime),
  &(pinfo->counter),
  &(pinfo->priority),
  &(pinfo->timeout),
  &(pinfo->itrealvalue),
  &(pinfo->starttime),
  &(pinfo->vsize),
  &(pinfo->rss),
  &(pinfo->rlim),
  &(pinfo->startcode),
  &(pinfo->endcode),
  &(pinfo->startstack),
  &(pinfo->kstkesp),
  &(pinfo->kstkeip),
  &(pinfo->signal),
  &(pinfo->blocked),
  &(pinfo->sigignore),
  &(pinfo->sigcatch),
  &(pinfo->wchan));
  fclose (fp);
  return 0;
}
int ProcessInfo::GetTime(int64_t& proc)
{
	procinfo pinfo;
	if(GetProcCpuInfo(pid,&pinfo)!=0)
		return -1;
	proc=pinfo.utime+pinfo.stime+pinfo.cstime+pinfo.cutime;
	return 0;
}

void ProcessInfo::GetMemoryInfo(unsigned int& topmem,unsigned int& mem)
{
	topmem=mem=0;
	char szFileName [256],
	    szStatStr [2048],
	    *s;
	  FILE *fp;

	  sprintf (szFileName, "/proc/%u/status", (unsigned) pid);

	  if (-1 == access (szFileName, R_OK)) {
	    return ;
	  } /** if **/

	  if ((fp = fopen (szFileName, "r")) == NULL) {
	    return ;
	  } /** IF_NULL **/

	  while ((s = fgets (szStatStr, 2048, fp)) != NULL) {
	      s = strstr (szStatStr, "VmRSS:");
	      if(s!=NULL){
	    	  //printf("%s",s);
	         sscanf (s+7, "%d",&mem);
	         if(mem>maxMem)
	        	 maxMem=mem;
	         break;
	      }
	  }
	  fclose (fp);
	  topmem=maxMem;
}
#endif

int ProcessInfo::GetCpu()
{
	std::unique_lock<mutex> lock(mtx);
	DWORD t2 = GetTickCount();
	DWORD dt = t2 - t1;
	if( dt>139 ){
		int64_t proc;
		if(GetTime(proc)==0)
		{
		    percent =(int)( ((proc-oldp)*100)/(cpuNum*dt));
		    t1 = t2;
		    oldp = proc;
		}
	}
    return(percent);
}
